package com.ihy.utils;


import com.ihy.domain.Role;
import com.ihy.domain.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.*;

public class JwtTokenUtils {

    //用于签名的私钥
    private static final String PRIVATE_KEY = "17CS3Flight";
    //签发者
    private static final String ISS = "JiaM";
    //过期时间1小时
    private static final long EXPIRATION_ONE_HOUR = 3600L;
    //过期时间1天
    private static final long EXPIRATION_ONE_DAY = 604800L;

    /**
     * 生成Token
     *
     * @param user           用户
     * @param expireTimeType 过期时间
     * @return token串
     */
    public static String createToken(User user, int expireTimeType) {
        //过期时间
        long expireTime;
        if (expireTimeType == 0) {
            expireTime = EXPIRATION_ONE_HOUR;
        } else {
            expireTime = EXPIRATION_ONE_DAY;
        }
        //Jwt头
        Map<String, Object> header = new HashMap<>();
        header.put("typ", "JWT");
        header.put("alg", "HS256");
        Map<String, Object> claims = new HashMap<>();
        //自定义有效载荷部分
        claims.put("username", user.getUsername());
        for (Role role : user.getRoles()) {
            claims.put("role", role.getName());
        }
        claims.put("date", new Date());
        return Jwts.builder()
                //发证人
                .setIssuer(ISS)
                //Jwt头
                .setHeader(header)
                //有效载荷
                .setClaims(claims)
                //设定签发时间
                .setIssuedAt(new Date())
                //设定过期时间
                .setExpiration(new Date(System.currentTimeMillis() + expireTime * 1000))
                //使用HS256算法签名，PRIVATE_KEY为签名密钥
                .signWith(SignatureAlgorithm.HS256, PRIVATE_KEY)
                .compact();
    }

    /**
     * 验证Token，返回数据只有id和account和type的User对象
     *
     * @param token token串
     * @return 用户信息
     */
    public static User checkToken(String token) {
        //封装角色信息
        HashSet<Role> roles = new HashSet<>();
        Role role1 = new Role();
        Claims claims = Objects.requireNonNull(getClaimsFromToken(token));
        role1.setName((String) claims.get("role"));
        roles.add(role1);
        //封装为User对象
        User user = new User();
        user.setUsername((String) claims.get("username"));
        user.setRoles(roles);
        user.setTime(new Date((Long) claims.get("date")));
        return user;
    }

    /**
     * 获取有效载荷
     *
     * @param token token串
     * @return 这最终是一个JSON映射，可以向其中添加任何值，但是为了方便起见，JWT标准名称作为类型安全的getter和setter提供
     */
    public static Claims getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser()
                    //设定解密私钥
                    .setSigningKey(PRIVATE_KEY)
                    //传入Token
                    .parseClaimsJws(token)
                    //获取载荷类
                    .getBody();
        } catch (Exception e) {
            return null;
        }
        return claims;
    }
}